import { phpGenerator, Order } from 'blockly/php'

function isInteger(str) {
    return /^\d+$/.test(str)
}

phpGenerator.forBlock['php_echo'] = function (block, generator) {
    const code = generator.valueToCode(block, 'text', Order.ATOMIC)
    return 'echo ' + code + ';\n';
}

phpGenerator.forBlock['php_print'] = function (block, generator) {
    const code = generator.valueToCode(block, 'text', Order.FUNCTION_CALL)
    return 'print_r( ' + code + ');\n';
}

phpGenerator.forBlock['controls_forever'] = function (block, generator) {
    const branch = generator.statementToCode(block, 'DO')
    return 'while(true) {\n' + branch + '}\n'
}

phpGenerator.forBlock['math_evenly_divisible'] = function (block, generator) {
    const argument1 = generator.valueToCode(block, 'DIVIDEND', Order.MODULUS) || '0'
    const argument2 = generator.valueToCode(block, 'DIVISOR', Order.MODULUS) || '0'
    return ['floor(' + argument1 + ' / ' + argument2 + ') * ' + argument2 + ' === 0', Order.NONE]
}

phpGenerator.forBlock['text_charAt'] = function (block, generator) {
    const argument1 = generator.valueToCode(block, 'VALUE', Order.FUNCTION_CALL) || "''"
    let argument2, code
    argument2 = generator.valueToCode(block, 'INDEX', Order.FUNCTION_CALL) || '1'
    if (block.getFieldValue('WHERE') === 'FROM_START') {
        argument2 = isInteger(argument2) ? String(Number(argument2) - 1) : argument2 + ' - 1'
        code = 'substr(' + argument1 + ', ' + argument2 + ', 1)';
    } else if (block.getFieldValue('WHERE') === 'FROM_END') {
        code = 'substr(' + argument1 + ', -' + argument2 + ', 1)';
    }
    return [code, Order.NONE]
}

phpGenerator.forBlock['text_getSubstring'] = function (block, generator) {
    const argument1 = generator.valueToCode(block, 'VALUE', Order.FUNCTION_CALL) || "''"
    let argument2, argument3
    argument2 = generator.valueToCode(block, 'INDEX1', Order.FUNCTION_CALL) || '1'
    argument3 = generator.valueToCode(block, 'INDEX2', Order.FUNCTION_CALL) || '1'
    if (block.getFieldValue('WHERE1') === 'FROM_START') {
        argument2 = isInteger(argument2) ? String(Number(argument2) - 1) : argument2 + ' - 1'
    } else if (block.getFieldValue('WHERE1') === 'FROM_END') {
        argument2 = '-(' + argument2 + ')';
    }
    if (block.getFieldValue('WHERE2') === 'FROM_END') {
        argument3 = isInteger(argument3) ? String(Number(argument3)) : '(' + argument3 + ')';
        argument3 = '-(' + argument3 + ')';
    }
    return ['substr(' + argument1 + ', ' + argument2 + ', ' + argument3 + ')', Order.NONE]
}

phpGenerator.forBlock['math_types'] = function (block, generator) {
    const map = { STRING: 'strval', NUMBER: 'floatval', BOOLEAN: 'boolval' }
    const argument1 = generator.valueToCode(block, 'VALUE', Order.ADDITION) || ''
    return [map[block.getFieldValue('TYPE')] + '(' + argument1 + ')', Order.NONE]
}

phpGenerator.forBlock['lists_push'] = function (block, generator) {
    const argument1 = generator.valueToCode(block, 'VALUE', Order.ADDITION) || ''
    const argument2 = generator.valueToCode(block, 'LIST', Order.ADDITION) || 'array()'
    return argument2 + '[] = ' + argument1 + ';'
}

phpGenerator.forBlock['lists_insert'] = function (block, generator) {
    const argument1 = generator.valueToCode(block, 'VALUE', Order.ADDITION) || 'null'
    const argument2 = generator.valueToCode(block, 'LIST', Order.ADDITION) || 'array()'
    let argument3 = generator.valueToCode(block, 'INDEX', Order.ADDITION) || '1'
    if (block.getFieldValue('WHERE') === 'FROM_START') {
        argument3 = isInteger(argument3) ? String(Number(argument3) - 1) : '(' + argument3 + ' - 1)';
    } else if (block.getFieldValue('WHERE') === 'FROM_END') {
        argument3 = '-(' + argument3 + ')';
    }
    return 'array_splice(' + argument2 + ', ' + argument3 + ', 0, ' + argument1 + ');';
}

phpGenerator.forBlock['lists_delete'] = function (block, generator) {
    const argument1 = generator.valueToCode(block, 'LIST', Order.ADDITION) || 'array()'
    let argument2 = generator.valueToCode(block, 'INDEX', Order.ADDITION) || '1'
    if (block.getFieldValue('WHERE') === 'FROM_START') {
        argument2 = isInteger(argument2) ? String(Number(argument2) - 1) : '(' + argument2 + ' - 1)';
    } else if (block.getFieldValue('WHERE') === 'FROM_END') {
        argument2 = '-(' + argument2 + ')';
    }
    return 'array_splice(' + argument1 + ', ' + argument2 + ', 1);';
}

phpGenerator.forBlock['lists_set'] = function (block, generator) {
    const argument1 = generator.valueToCode(block, 'LIST', Order.ADDITION) || 'array()'
    const argument3 = generator.valueToCode(block, 'VALUE', Order.ADDITION) || 'null'
    let argument2 = generator.valueToCode(block, 'INDEX', Order.ADDITION) || '1'
    if (block.getFieldValue('WHERE') === 'FROM_START') {
        argument2 = isInteger(argument2) ? String(Number(argument2) - 1) : '(' + argument2 + ' - 1)';
    } else if (block.getFieldValue('WHERE') === 'FROM_END') {
        argument2 = '-(' + argument2 + ')';
    }
    return argument1 + '[' + argument2 + '] = ' + argument3 + ';';
}

phpGenerator.forBlock['lists_get'] = function (block, generator) {
    const argument1 = generator.valueToCode(block, 'LIST', Order.ADDITION) || 'array()'
    let argument2 = generator.valueToCode(block, 'INDEX', Order.ADDITION) || '1'
    if (block.getFieldValue('WHERE') === 'FROM_START') {
        argument2 = isInteger(argument2) ? String(Number(argument2) - 1) : '(' + argument2 + ' - 1)';
    } else if (block.getFieldValue('WHERE') === 'FROM_END') {
        argument2 = '-(' + argument2 + ')';
    }
    return [argument1 + '[' + argument2 + ']', Order.NONE]
}

phpGenerator.forBlock['lists_index'] = function (block, generator) {
    const argument1 = generator.valueToCode(block, 'LIST', Order.ADDITION) || 'array()'
    const argument2 = generator.valueToCode(block, 'VALUE', Order.ADDITION) || "''"
    let code
    if (block.getFieldValue('WHICH') === 'FIRST') {
        code = 'array_search(' + argument2 + ', ' + argument1 + ') + 1';
    } else if (block.getFieldValue('WHICH') === 'LAST') {
        code = 'count(' + argument1 + ') - array_search(array_reverse(' + argument1 + ', true), ' + argument2 + ', true) + 1'
    }
    return [code, Order.NONE]
}

phpGenerator.forBlock['lists_includes'] = function (block, generator) {
    const argument1 = generator.valueToCode(block, 'LIST', Order.ADDITION) || 'array()'
    const argument2 = generator.valueToCode(block, 'VALUE', Order.ADDITION) || "''"
    return ['in_array(' + argument2 + ', ' + argument1 + ')', Order.NONE]
}

phpGenerator.forBlock['php_get'] = function (block, generator) {
    const code = generator.valueToCode(block, 'key', Order.ATOMIC) || "''";
    return ['$_GET[' + code + ']', 0];
}

phpGenerator.forBlock['php_post'] = function (block, generator) {
    const code = generator.valueToCode(block, 'key', Order.ATOMIC) || "''";
    return ['$_POST[' + code + ']', 0];
}

phpGenerator.forBlock['php_html_safe'] = function (block, generator) {
    const code = generator.valueToCode(block, 'html', Order.ATOMIC) || "''";
    return 'htmlspecialchars(' + code + ');\n';
}

phpGenerator.forBlock['php_require'] = function (block, generator) {
    const code = generator.valueToCode(block, 'url', Order.ATOMIC) || "''"

    return 'require(' + code + ');\n';
}

phpGenerator.forBlock['php_include'] = function (block, generator) {
    const code = generator.valueToCode(block, 'url', Order.ATOMIC) || "''"
    return 'include ' + code + ';\n';
}

phpGenerator.forBlock['php_text'] = function (block, generator) {
    const code = generator.valueToCode(block, 'text', Order.ATOMIC) || "''"
    return [code, 0];
}

phpGenerator.forBlock['php_get_cookie'] = function (block, generator) {
    const code = generator.valueToCode(block, 'key', Order.ATOMIC) || "''"
    return ['$_COOKIE[' + code + ']', 0];
}

phpGenerator.forBlock['php_get_session'] = function (block, generator) {
    const code = generator.valueToCode(block, 'key', Order.ATOMIC) || "''"
    return ['$_SESSION[' + code + ']', 0];
}

phpGenerator.forBlock['php_md5'] = function (block, generator) {
    const code = generator.valueToCode(block, 'text', Order.ATOMIC) || "''"
    return ['md5(' + code + ')', 0];
}

phpGenerator.forBlock['php_start_session'] = function () {
    return 'session_start();\n';
}

phpGenerator.forBlock['php_sha256'] = function (block, generator) {
    const code = generator.valueToCode(block, 'text', Order.ATOMIC) || "''"
    return ['hash("sha256",' + code + ')', 0];
}

phpGenerator.forBlock['php_read_file'] = function (block, generator) {
    const code = generator.valueToCode(block, 'path', Order.ATOMIC) || "''"
    return ['file_get_contents(' + code + ')', 0];
}

phpGenerator.forBlock['php_sql_connect_po'] = function (block, generator) {
    const path = generator.valueToCode(block, 'path', Order.ATOMIC) || "'localhost'"
    const name = generator.valueToCode(block, 'name', Order.ATOMIC) || "'mysql'"
    const pw = generator.valueToCode(block, 'pw', Order.ATOMIC) || "'123456'"
    const db_name = generator.valueToCode(block, 'db_name', Order.ATOMIC) || "'mysql'"
    return ['mysqli_connect(' + path + ', ' + name + ', ' + pw + ', ' + db_name + ')', 0];
}

phpGenerator.forBlock['php_write_session'] = function (block, generator) {
    const key = generator.valueToCode(block, 'key', Order.ATOMIC) || "''"
    const value = generator.valueToCode(block, 'value', Order.ATOMIC) || "''"
    return "$_SESSION[" + key +"] = " + value + ";";
}

phpGenerator.forBlock['php'] = function (block, generator) {
    const code = generator.statementToCode(block, 'block', Order.ATOMIC)
    return '<?php \n'+code+'\n ?>\n';
}

phpGenerator.forBlock['php_write'] = function (block, generator) {
    const path = generator.valueToCode(block, 'path', Order.ATOMIC) || "''"
    const text = generator.valueToCode(block, 'text', Order.ATOMIC) || "''"
    return "file_put_contents(" + path + ", " + text + ");\n";
}

phpGenerator.forBlock['php_cors'] = function () {
    return "header('Access-Control-Allow-Origin: *');\n";
}

phpGenerator.forBlock['html_h1'] = function (block, generator) {
    const text = generator.statementToCode(block, 'text', Order.ATOMIC)
    const attr = generator.statementToCode(block, 'attr', Order.ATOMIC)
    return '<h1 '+ attr + '>' + text + "</h1>\n";
}

function createHtmlCode(name,text,attr){
    if(attr){
        attr = " "+attr.slice(2).split("\n  ").join(" ").split("\n").join("")
    }else{
        attr=""
    }
    if(text){
        if(text.replaceAll(/ |\n/g,"").startsWith("<")){
            text = "\n"+(text)
            if(text.slice(-1) == ">"){
                text = text + "\n"
            }
        }else{
            text=text.slice(2)
        }
    }else {
        text = ""
    }
    return `<${name}${attr}>${text}</${name}>\n`;
}

function escapeHTML(text) {
  let map = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#039;'
  };

  return text.replace(/[&<>"']/g, function(m) {
    return map[m];
  });
}


phpGenerator.forBlock['html_customize'] = function (block, generator) {
    const name = block.getFieldValue('NAME')
    const text = generator.statementToCode(block, 'text', Order.ATOMIC)
    const attr = generator.statementToCode(block, 'attr', Order.ATOMIC)
    return createHtmlCode(name,text,attr)
}

phpGenerator.forBlock['html_customize_attr'] = function (block, generator) {
    const name = block.getFieldValue('name')
    const value = block.getFieldValue('value')
    return name+'="'+value+'"\n';
}

phpGenerator.forBlock['html_customize_text'] = function (block, generator) {
    const text = block.getFieldValue('text')
    return escapeHTML(text);
}

phpGenerator.forBlock['html_style'] = function (block, generator) {
    const css = generator.statementToCode(block, 'css', Order.ATOMIC)
    return 'style="'+ css + '"\n';
}

phpGenerator.forBlock['html_style_width'] = function (block, generator) {
    const value = generator.valueToCode(block, 'value', Order.ATOMIC)
    let unit
    if (block.getFieldValue('unit') === 'px') {
        unit = 'px'
    } else{
        unit = '%'
    }
    return 'width: ' + value + unit + ';';
}

phpGenerator.forBlock['php_get_time'] = function (block, generator) {
    return ['time()',0];
}

phpGenerator.forBlock['mysqli_connect_error'] = function (block, generator) {
    return ['mysqli_connect_error()', 0];
}

phpGenerator.forBlock['php_sql_query'] = function (block, generator) {
    const sql = generator.valueToCode(block, 'sql', Order.ATOMIC) || '"'+"INSERT INTO Test (`a`, `b`, `c`) VALUES ('1', '2', '3')"+'"'
    const object = generator.valueToCode(block, 'object', Order.ATOMIC) || '$conn'
    return ['mysqli_query(' + object + ', ' + sql + ')', 0];
}